perm filename CAMERA.SAI[SYS,HE]2 blob sn#019463 filedate 1973-01-10 generic text, type T, neo UTF8
COMMENT ⊗   VALID 00010 PAGES 
RECORD PAGE   DESCRIPTION
 00001 00001
 00002 00002	BEGIN "GILCAM" 
 00005 00003	SIMPLE PROCEDURE DATXFR  ⊃   READS DATA IN GILL'S FORMAT
 00008 00004	PROCEDURE PANTIL_CAM(INTEGER CLENSREAL PPOT,TPOT,FPOT
 00012 00005	SIMPLE MESSAGE PROCEDURE CAM_UPDATE
 00018 00006	SIMPLE MESSAGE PROCEDURE CHNG_LENS(INTEGER RLENS)
 00021 00007	SIMPLE MESSAGE PROCEDURE CAM_CENTER(INTEGER RLENS REAL XTC,YTC,ZTC)
 00024 00008	
 00027 00009	SIMPLE PROCEDURE TESTIT
 00030 00010	
 00031 ENDMK
⊗;
BEGIN "GILCAM" 
REQUIRE "PREAMB.SAI[SYS,HE]" SOURCE_FILE;
REQUIRE "HELIB[1,3]" LIBRARY;
REQUIRE -1 NEW_ITEMS;

DEFINE ⊃="COMMENT";

⊃ THIS IS THE CAMERA MINDER .  IT HOUSES THE FOLLOWING MESSAGE PROCEDURES:
  CAM_INIT-INITIALIZES THE CAMERA MODEL FROM ONE OF IRWIN'S RELAXED MODELS.
  CAM_UPDATEATE-READS THE POTS AND CREATES A NEW  CAMERA TRANSFORM MATRIX.
  CHNG_LENS(LENS), MOVE_CAM(PAN,TILT), CHNG_FOCUS(RANGE)-DO THE OBVIOUS.
  CAM_CENTER(LENS,X,Y,Z)-CENTER THE CAMERA ON TABLE COORDS X,Y,Z.
  CAM_PRED(LENS,X,Y,Z)-COMPUTE THE MODEL FOR THE CAMERA ON TABLE COORDS X,Y,Z,
		       AND STORE IT INTO CAMERA_PREDI.

  THE CAMERA TRANSFROM MATRIX IS A 10X3 MATRIX:
	1:3 X 1:3   THE COLINEATION MATRIX.
	 4  X 1:3   THE LENS CENTER.
	 5  X 1:3   THE CENTER OF THE FIELD OF VIEW
	6:8 X 1:3   THE INVERSE COLINEATION MATRIX.
	 9  X 1:3   CAMPAN, CAMTIL, CAMRANG
	 10 X 1:2   CAMERA NO., CAMLENS

   A NEW ITEM IS GENERATED, PUT IN CURCAM, AND THIS MATRIX BECOMES
   ITS DATUM.
   ERRORS: 1-SERVO PROBLEMS(SERVO). 
	   2-LENS OUT OF BOUNDS(CHNG_LENS,CAM_CENTER).
	   3-PAN OUT OF BOUNDS(MOVE_CAM,CAM_CENTER).
	   4-TILT OUT OF BOUNDS(MOVE_CAM,CAM_CENTER).
	   5-FOCUS OUT OF BOUNDS(CHNG_FOCUS,CAM_CENTER). 
	   6-LENS CHANGER GOOFED(CHNG_LENS).
	   7-LOOKUP FAILED(DATXFR). 
	   8-NOT ENOUGH READINGS(CAM_UPDATE).
           9-POTS TOO NOISY(CAM_UPDATE). 
	  10-AD NOT AVAILABLE(CAM_UPDATE).
;

REAL ARRAY MCOL,MICOL [1:3,1:3];  ⊃ WHERE I KEEP CURRENT CAMERA XFORM;
REAL ARRAY LCEN[1:3];		  ⊃ AND LENS CENTER ;

REAL ARRAY PPOT0,PPOTD,TPOT0,TPOTD,FPOT0,FPOTD,MART,SWING,
           FOC,FOCLEN0,FOCLENG[1:4],DP,P0[1:4,1:3],PP[1:4,1:2];
INTEGER MESS,BLOCK,DUMMY;

DEFINE XDATA="3",STX="1 STEP 1 UNTIL",CRLF="&'15&'12",
 	YES="INCHWL=""Y""";
SIMPLE PROCEDURE DATXFR;  ⊃   READS DATA IN GILL'S FORMAT;
  BEGIN BOOLEAN FLAG;
        INTEGER DUMMY;
	DEFINE DATASET="""DATA[SYS,HE]""";
	DEFINE XFR(X)="ARRYIN(XDATA,X,1)";
	OPEN(XDATA,"DSK",12,3,0,0,0,0);
	LOOKUP(XDATA,DATASET,FLAG);
	IF FLAG THEN BEGIN OUTSTR("DATXFR-FAILED: LOOKUP FAILED FOR "&
				   DATASET CRLF);
 			CAMFLG←7; RETURN; END;
	IF TYP_CAM THEN OUTSTR("DATXFR: RETRIEVING "&DATASET&CVS(BLOCK)CRLF);
	USETI(XDATA,1); DUMMY←WORDIN(XDATA);
	USETI(XDATA,BLOCK);
    XFR(PPOT0[BLOCK]); XFR(PPOTD[BLOCK]); XFR(TPOT0[BLOCK]); XFR(TPOTD[BLOCK]);
    XFR(FPOT0[BLOCK]); XFR(FPOTD[BLOCK]);
    XFR(MART[BLOCK]);  XFR(SWING[BLOCK]);
    XFR("PP[BLOCK,1]");XFR("PP[BLOCK,2]");XFR("P0[BLOCK,1]");XFR("P0[BLOCK,2]");
    XFR("P0[BLOCK,3]");XFR("DP[BLOCK,1]");XFR("DP[BLOCK,2]");XFR("DP[BLOCK,3]");
    XFR(FOC[BLOCK]); XFR(FOCLEN0[BLOCK]); XFR(FOCLENG[BLOCK]);
	RELEASE(XDATA);
  END "DATXFR";

SIMPLE PROCEDURE SERVO;
  BEGIN	EXTERNAL PROCEDURE SPWON(INTEGER TIC;REFERENCE INTEGER ADDR);
	EXTERNAL INTEGER STATUS,L1,L2,L3,P1,P2,P3,E1,E2,E3,TSERVO;
        EXTERNAL PROCEDURE SPWOFF;

    SPWON(1,TSERVO);
    WHILE ¬(STATUS LAND 1) DO;
    IF (STATUS≥'100)∧(STATUS<'100000) THEN BEGIN
       OUTSTR("SERVO-FAILED: STATUS="&CVOS(STATUS)CRLF);
       CAMFLG←1;        END;
    SPWOFF; CALL(1,"SLEEP"); 
    IF DEB_CAM THEN BEGIN
    OUTSTR("SERVO: E1="&CVS(E1)&"  E2="&CVS(E2)&"  E3="&CVS(E3)CRLF);
    OUTSTR("       L1="&CVS(L1)&"  L2="&CVS(L2)&"  L3="&CVS(L3)CRLF);
    OUTSTR("       P1="&CVS(P1)&"  P2="&CVS(P2)&"  P3="&CVS(P3)CRLF); END;
  END "SERVO";

SIMPLE REAL PROCEDURE LNS(REAL X; INTEGER RLENS);
      RETURN (X*FOC[RLENS]/(X-FOC[RLENS]));
PROCEDURE PANTIL_CAM(INTEGER CLENS;REAL PPOT,TPOT,FPOT;
  		      REAL ARRAY COL,ICOL,CENTER);
 ⊃ Compute the transformation matrices for the camera model
   given by LENS and the last pots readings;
  BEGIN INTEGER I,J;   
	REAL   ACC,FMX,FMY,PAN,TILT;
        REAL ARRAY RP,RT,RPT,RS,R[1:3,1:3],C[1:3];
	FORTRAN REAL PROCEDURE SIN;
	FORTRAN REAL PROCEDURE COS;
	REQUIRE "SOBMAT[SYS,HE]" LOAD_MODULE;
	EXTERNAL PROCEDURE INVRT(REAL ARRAY A,AI);

	PAN←PPOTD[CLENS]*PPOT+PPOT0[CLENS];
        TILT←TPOTD[CLENS]*TPOT+TPOT0[CLENS];
	FMY←FPOTD[CLENS]*FPOT+FPOT0[CLENS]; FMX←FMY*MART[CLENS];

	RP[2,3]←-1;    RPT[1,1]←RP[1,1]←RP[3,2]←-SIN(PAN);
        RP[3,1]←-(RPT[1,2]←RP[1,2]←COS(PAN));
	RT[1,1]←1;     RPT[2,3]←-(RT[2,2]←RT[3,3]←COS(TILT));
        R[3,3]←RPT[3,3]←RT[2,3]←-(RT[3,2]←SIN(TILT));
	RPT[2,1]←RT[2,3]*RP[3,1];     RPT[2,2]←RT[2,3]*RP[3,2]; 
	R[3,1]←RPT[3,1]←RT[3,3]*RP[3,1];     R[3,2]←RPT[3,2]←RT[3,3]*RP[3,2];
	RS[3,3]←1;  RS[1,1]←RS[2,2]←COS(SWING[CLENS]);
	RS[2,1]←-(RS[1,2]←SIN(SWING[CLENS]));
	R[1,1]←RS[1,1]*RPT[1,1]+RS[1,2]*RPT[2,1];
	R[1,2]←RS[1,1]*RPT[1,2]+RS[1,2]*RPT[2,2];   R[1,3]←RS[1,2]*RPT[2,3];
	R[2,1]←RS[2,1]*RPT[1,1]+RS[2,2]*RPT[2,1];
	R[2,2]←RS[2,1]*RPT[1,2]+RS[2,2]*RPT[2,2];    R[2,3]←RS[2,2]*RPT[2,3];

	C[1]←P0[CLENS,1]+R[1,1]*DP[CLENS,1]+R[2,1]*DP[CLENS,2]+R[3,1]*DP[CLENS,3];
	C[2]←P0[CLENS,2]+R[1,2]*DP[CLENS,1]+R[2,2]*DP[CLENS,2]+R[3,2]*DP[CLENS,3];
	C[3]←P0[CLENS,3]+R[1,3]*DP[CLENS,1]+R[2,3]*DP[CLENS,2]+R[3,3]*DP[CLENS,3];

	⊃ -FMX/333 and PP[2]-PP[1]/333 are corrections for
	  the non-orthogonality of the TV scan axes;
	FOR I←1 STEP 1 UNTIL 3 DO BEGIN 
      	    COL[I,1]←R[I,1];   COL[I,2]←R[I,2];   ACC←0;
	    FOR J←1 STEP 1 UNTIL 3 DO	ACC←ACC-R[I,J]*C[J];
	    COL[I,3]←ACC    END;
	FOR J←1 STEP 1 UNTIL 3 DO BEGIN 
	    COL[2,J]←-FMX/333*COL[1,J]+FMY*COL[2,J]
		     +(PP[CLENS,2]-PP[CLENS,1]/333)*COL[3,J];
	    COL[1,J]←FMX*COL[1,J]+PP[CLENS,1]*COL[3,J]; END;
    INVRT(COL,ICOL); ARRTRAN(CENTER,C);
  END "PANTIL_CAM";
SIMPLE MESSAGE PROCEDURE CAM_UPDATE;
  BEGIN INTEGER SFOC,STIL,SPAN,IND,FMAX,FMIN,TMAX,TMIN,PMAX,PMIN,
	        DIFFOC,DIFTIL,DIFPAN,SIND,UPDFLG;
	EXTERNAL INTEGER L1,L2,L3,P1,P2,P3,STATUS,TSERVO;
	FORTRAN REAL PROCEDURE SQRT(REAL X);
       	EXTERNAL PROCEDURE SPWON(INTEGER TIC;REFERENCE INTEGER ADDR);
        EXTERNAL PROCEDURE SPWOFF;
	LABEL ETA;

 ETA:	SFOC←STIL←SPAN←0; FMAX←TMAX←PMAX←-10000; FMIN←TMIN←PMIN←10000;
	STATUS←1; SPWON(1,TSERVO);
	FOR IND←0 STEP 1 UNTIL 39 DO BEGIN
	    STATUS←4; WHILE ¬(STATUS LAND 1) DO;
	    IF (STATUS≥'100)∧(STATUS<'100000) THEN DONE;
	    SFOC←SFOC+P1; STIL←STIL+P2; SPAN←SPAN+P3;
	    IF P1>FMAX THEN FMAX←P1; IF P1<FMIN THEN FMIN←P1;
	    IF P2>TMAX  THEN TMAX←P2;  IF P2<TMIN  THEN TMIN←P2;
	    IF P3>PMAX   THEN PMAX←P3;   IF P3<PMIN   THEN PMIN←P3;
	          		     END;
	SPWOFF;

	IF   IND>0 
	THEN BEGIN L1←FOCPOT←SFOC/IND; L2←TILPOT←STIL/IND; L3←PANPOT←SPAN/IND;
	     IF DEB_CAM THEN OUTSTR("CAM_UPDATE: "&
	     "FP="&CVG(FOCPOT)&"  TP="&CVG(TILPOT)&"  PP="&CVG(PANPOT)CRLF);

	     IF   IND<30
	     THEN BEGIN OUTSTR("CAM_UPDATE: NOT ENOUGH READINGS ("&
				CVS(IND)&")"CRLF); UPDFLG←8; END
	     ELSE BEGIN DIFFOC←FMAX-FMIN; DIFTIL←TMAX-TMIN; DIFPAN←PMAX-PMIN;
	          IF DEB_CAM THEN OUTSTR("CAM_UPDATE: "&
	          "DF="&CVS(DIFFOC)&"  DT="&CVS(DIFTIL)&"  DP="&CVS(DIFPAN)CRLF);
		  SIND←4*SQRT(IND);
		  IF (DIFPAN/SIND>.5)∨(DIFTIL/SIND>.25)∨(DIFFOC/SIND>1)
		  THEN BEGIN 
		     OUTSTR("CAM_UPDATE: POTS TOO NOISY ("&CVS(DIFFOC)&"  "&
			     CVS(DIFTIL)&"  "&CVS(DIFPAN)&")"CRLF);
		     UPDFLG←9; END; END; END
	ELSE BEGIN OUTSTR("CAM_UPDATE: AD NOT AVAILABLE"CRLF); UPDFLG←10; END;
	IF UPDFLG≠0 THEN BEGIN
	OUTSTR("...TYPE Y TO TRY AGAIN:"CRLF);
        IF   YES 
        THEN BEGIN UPDFLG←0; GOTO ETA; END 
        ELSE BEGIN CAMFLG←UPDFLG;
             IF CAMFLG=10 THEN BEGIN
	     OUTSTR("CAM_UPDATE-FAILED: CAMERA_MODEL NOT UPDATED"CRLF); RETURN;
	     END; END; END;

	PANTIL_CAM (CAMLENS,PANPOT,TILPOT,FOCPOT,MCOL,MICOL,LCEN);

	⊃ Now to update the global model;

	ARRBLT (CAMERA_MODEL[1,1],MCOL[1,1],9);
  	ARRBLT (CAMERA_MODEL[6,1],MICOL[1,1],9);
	ARRBLT (CAMERA_MODEL[4,1],LCEN[1],3);
	CAMERA_MODEL[5,1] ← PP[CAMLENS,1];
	CAMERA_MODEL[5,2] ← PP[CAMLENS,2];
	CAMERA_MODEL[5,3] ← 1.0;
	CAMERA_MODEL[9,1]←CAMPAN←PPOTD[CAMLENS]*PANPOT+PPOT0[CAMLENS];
        CAMERA_MODEL[9,2]←CAMTIL←TPOTD[CAMLENS]*TILPOT+TPOT0[CAMLENS];
        CAMERA_MODEL[9,3]←CAMRANG←LNS(FOCLEN0[CAMLENS]+
		          FOCLENG[CAMLENS]*FOCPOT,CAMLENS);
        CAMERA_MODEL[10,2]←CAMLENS;
	CURCAM ← GLOBAL NEW (CAMERA_MODEL);

	IF DEB_CAM THEN OUTSTR("CAM_UPDATE: "&
	"CAMPAN="&CVG(CAMPAN)&"  CAMTIL="&CVG(CAMTIL)&"  CAMRANG="&CVG(CAMRANG)
	CRLF);

  END "CAM_UPDATE";

SIMPLE PROCEDURE HAT;
  BEGIN EXTERNAL PROCEDURE CALLEN;
	EXTERNAL INTEGER LENS;
	CALLEN; CAMLENS←LENS+1; CAM_UPDATE;
  END "HAT";

SIMPLE REAL PROCEDURE COSQR(REAL A,B,C);
  ⊃ Solves the eq. Acos(x)+Bsin(x)+C=0 for x;
  BEGIN FORTRAN REAL PROCEDURE ACOS(REAL X);
	FORTRAN REAL PROCEDURE SQRT(REAL X);
	REAL K,M,N;
    
    K←A*C; M←A↑2+B↑2; N←B↑2-C↑2;
    IF   A*B<0
    THEN RETURN(ACOS(-(K/M)+SQRT((K/M)↑2+(N/M))))
    ELSE RETURN(ACOS(-(K/M)-SQRT((K/M)↑2+(N/M))));
  END "COSQR";
SIMPLE MESSAGE PROCEDURE CHNG_LENS(INTEGER RLENS);
  BEGIN EXTERNAL PROCEDURE CALLEN;
	EXTERNAL INTEGER STATUS,LENS;
    IF (RLENS<1)∨(RLENS>4) THEN BEGIN
    OUTSTR("CHNG_LENS-FAILED: LENS NO. OUT OF BOUNDS ("&CVS(RLENS)&")"CRLF); 
    CAMFLG←2; RETURN; END;
    CALLEN;
    IF   LENS≠RLENS-1 
    THEN BEGIN LENS←RLENS-1; STATUS←'20; SERVO; CALLEN;
               IF LENS≠RLENS-1 
	       THEN BEGIN OUTSTR("CHNGE_LENS: I GOOFED, NOW YOU HAVE LENS NO. "&
				 CVS(LENS+1)CRLF); CAMFLG←6; END; END;
    CAMLENS←LENS+1; CAM_UPDATE;
  END "CHNG_LENS";

SIMPLE MESSAGE PROCEDURE MOVE_CAM(REAL PAN,TILT);
  BEGIN REAL LL2,LL3;
	EXTERNAL INTEGER STATUS,L2,L3;
    LL3←(PAN-PPOT0[CAMLENS])/PPOTD[CAMLENS];
    LL2←(TILT-TPOT0[CAMLENS])/TPOTD[CAMLENS];
    IF (LL2≥-340)∨(LL2≤-1870) THEN BEGIN
       OUTSTR("MOVE_CAM-FAILED: TILT OUT OF BOUNDS (LL2="&CVS(LL2)&")"CRLF);
       CAMFLG←4; END;
    IF (LL3≥2000)∨(LL3≤-2000) THEN BEGIN
       OUTSTR("MOVE_CAM-FAILED: PAN OUT OF BOUNDS (LL3="&CVS(LL3)&")"CRLF);
       CAMFLG←3; END;
    IF CAMFLG≠0 THEN RETURN;
    L3←LL3; L2←LL2; STATUS←'10; SERVO;
    CAM_UPDATE;
  END "MOVE_CAM";

SIMPLE MESSAGE PROCEDURE CHNG_FOCUS(REAL RANG);
  BEGIN REAL LL1;
	EXTERNAL INTEGER STATUS,L1;
       LL1←(LNS(RANG,CAMLENS)-FOCLEN0[CAMLENS])/FOCLENG[CAMLENS];
       IF (LL1≥1900)∨(LL1≤0) 
       THEN BEGIN OUTSTR("CHNGE_FOC-FAILED: FOCUS OUT OF BOUNDS (LL1="&
			  CVS(LL1)&")"CRLF); CAMFLG←5; RETURN; END;
       L1←LL1; STATUS←'10; SERVO; 
       CAM_UPDATE;
  END "CHNG_FOCUS";
SIMPLE MESSAGE PROCEDURE CAM_CENTER(INTEGER RLENS; REAL XTC,YTC,ZTC);
  BEGIN REAL XCC,YCC,ZCC,D,RANG,PAN,TILT,LL1,LL2,LL3;
	EXTERNAL PROCEDURE CALLEN;
	EXTERNAL INTEGER LENS,L1,L2,L3,STATUS;
	FORTRAN REAL PROCEDURE SIN(REAL X);
	FORTRAN REAL PROCEDURE COS(REAL X);

    IF (RLENS<1)∨(RLENS>4) THEN BEGIN
    OUTSTR("CAM_CENTER-FAILED: LENS NO. OUT OF BOUNDS ("&CVS(RLENS)&")"CRLF); 
    CAMFLG←2; RETURN; END;

    XCC←P0[RLENS,1]-XTC; YCC←P0[RLENS,2]-YTC; ZCC←P0[RLENS,3]-ZTC;
    PAN←COSQR(YCC,-XCC,DP[RLENS,1]);
    D←XCC*COS(PAN)+YCC*SIN(PAN);
    TILT←COSQR(ZCC,-D,-DP[RLENS,2]);
    RANG←D*COS(TILT)+ZCC*SIN(TILT)-DP[RLENS,3];

    LL3←(PAN-PPOT0[RLENS])/PPOTD[RLENS];
    LL2←(TILT-TPOT0[RLENS])/TPOTD[RLENS];
    LL1←(LNS(RANG,RLENS)-FOCLEN0[RLENS])/FOCLENG[RLENS];
    IF (LL2≥-340)∨(LL2≤-1870) THEN BEGIN
       OUTSTR("CAM_CENTER¬FAILED: TILT OUT OF BOUNDS (LL2="&CVS(LL2)&")"CRLF);
       CAMFLG←4; END;
    IF (LL3≥2000)∨(LL3≤-2000) THEN BEGIN
       OUTSTR("CAM_CENTER-FAILED: PAN OUT OF BOUNDS (LL3="&CVS(LL3)&")"CRLF);
       CAMFLG←3; END;
    IF (LL1≥1900)∨(LL1≤0) THEN BEGIN
       OUTSTR("CAM_CENTER-FAILED: FOCUS OUT OF BOUNDS (LL1="&CVS(LL1)&")"CRLF);
       CAMFLG←5; END;
    IF CAMFLG≠0 THEN RETURN;

    L1←LL1; L2←LL2; L3←LL3;
    CALLEN;
    IF   LENS≠RLENS-1 THEN BEGIN LENS←RLENS-1; STATUS←'30; END ELSE STATUS←'10;
    SERVO;
    CALLEN;
    IF   LENS≠RLENS-1 
    THEN BEGIN OUTSTR("CAM_CENTER: I GOOFED, NOW YOU HAVE LENS NO. "&
                       CVS(LENS+1)CRLF); CAMFLG←6; END;
    CAMLENS←LENS+1; CAM_UPDATE;

  END "CAM_CENTER";

SIMPLE MESSAGE PROCEDURE CAM_PRED(INTEGER RLENS; REAL XTC,YTC,ZTC);
  BEGIN REAL XCC,YCC,ZCC,D,RANG,PAN,TILT,LL1,LL2,LL3;
	FORTRAN REAL PROCEDURE SIN(REAL X);
	FORTRAN REAL PROCEDURE COS(REAL X);

    IF (RLENS<1)∨(RLENS>4) THEN BEGIN
    OUTSTR("CAM_PRED-FAILED: LENS NO. OUT OF BOUNDS ("&CVS(RLENS)&")"CRLF); 
    CAMFLG←2; RETURN; END;

    XCC←P0[RLENS,1]-XTC; YCC←P0[RLENS,2]-YTC; ZCC←P0[RLENS,3]-ZTC;
    PAN←COSQR(YCC,-XCC,DP[RLENS,1]);
    D←XCC*COS(PAN)+YCC*SIN(PAN);
    TILT←COSQR(ZCC,-D,-DP[RLENS,2]);
    RANG←D*COS(TILT)+ZCC*SIN(TILT)-DP[RLENS,3];

    LL3←(PAN-PPOT0[RLENS])/PPOTD[RLENS];
    LL2←(TILT-TPOT0[RLENS])/TPOTD[RLENS];
    LL1←(LNS(RANG,RLENS)-FOCLEN0[RLENS])/FOCLENG[RLENS];
    IF (LL2≥-340)∨(LL2≤-1870) THEN BEGIN
       OUTSTR("CAM_PRED¬FAILED: TILT OUT OF BOUNDS (LL2="&CVS(LL2)&")"CRLF);
       CAMFLG←4; END;
    IF (LL3≥2000)∨(LL3≤-2000) THEN BEGIN
       OUTSTR("CAM_PRED-FAILED: PAN OUT OF BOUNDS (LL3="&CVS(LL3)&")"CRLF);
       CAMFLG←3; END;
    IF (LL1≥1900)∨(LL1≤0) THEN BEGIN
       OUTSTR("CAM_PRED-FAILED: FOCUS OUT OF BOUNDS (LL1="&CVS(LL1)&")"CRLF);
       CAMFLG←5; END;
    IF CAMFLG≠0 THEN RETURN;

    PANTIL_CAM (RLENS,LL3,LL2,LL1,MCOL,MICOL,LCEN);
	ARRBLT (CAMERA_PREDI[1,1],MCOL[1,1],9);
  	ARRBLT (CAMERA_PREDI[6,1],MICOL[1,1],9);
	ARRBLT (CAMERA_PREDI[4,1],LCEN[1],3);
	CAMERA_PREDI[5,1] ← PP[CAMLENS,1];
	CAMERA_PREDI[5,2] ← PP[CAMLENS,2];
	CAMERA_PREDI[5,3] ← 1.0;
	CAMERA_PREDI[9,1]←PAN;
        CAMERA_PREDI[9,2]←TILT;
        CAMERA_PREDI[9,3]←RANG;
        CAMERA_PREDI[10,2]←RLENS;

  END "CAM_PRED";

SIMPLE MESSAGE PROCEDURE CAM_INIT;
  BEGIN	CAMFLG←0;
        FOR BLOCK←1 STEP 1 UNTIL 4 DO DATXFR;	⊃ JUST READ IN A MODEL;
  END"CAM_INIT";
SIMPLE PROCEDURE TESTIT;
  BEGIN STRING COORD;
        REAL X,Y,Z,NPAN,NTILT,NRANG;
        INTEGER NLENS,REQUEST;
        LABEL TIT,TES;
   TIT:	OUTSTR("1-CHANGE THE LENS"CRLF&
	       "2-PAN AND TILT THE CAMERA"CRLF&
	       "3-FOCUS ON A GIVEN RANGE"CRLF&
	       "4-CENTER THE CAMERA ON A GIVEN POINT"CRLF&
	       "5-COMPLEMENT DEB_CAM"CRLF);
   TES: OUTSTR("...TYPE THE NO. OF THE PROCEDUE YOU WANT TO TEST NOW="CRLF);
	REQUEST←CVD(INCHWL); 
	IF (REQUEST<1)∨(REQUEST>5) THEN BEGIN 
	OUTSTR("TESTIT-FAILED: ILLEGAL PROCEDURE NO ("&CVS(REQUEST)&")"CRLF);
        GOTO TIT; END;
	CASE REQUEST OF BEGIN
	BEGIN ⊃ 0;						END;
	BEGIN ⊃ 1; OUTSTR("...TYPE NO. OF LENS="CRLF);
		   NLENS←CVD(INCHWL); CHNG_LENS(NLENS);	END;
	BEGIN ⊃ 2; OUTSTR("...TYPE PAN AND TILT IN RADS,"&
			  " EACH FOLLOWED BY C.R="CRLF);
		   COORD←INCHWL; NPAN←REALSCAN(COORD,MESS);
		   COORD←INCHWL; NTILT←REALSCAN(COORD,MESS);
		   MOVE_CAM(NPAN,NTILT);			END;
	BEGIN ⊃ 3; OUTSTR("...TYPE RANGE TO FOCUS ON="CRLF);
		   COORD←INCHWL; NRANG←REALSCAN(COORD,MESS);
		   CHNG_FOCUS(NRANG);				END;
	BEGIN ⊃ 4; OUTSTR("TYPE IN LENS N0."&
			  "AND X,Y,Z OF CENTER IN TABLE COORDINATES"CRLF&
                          "EACH FOLLOWED BY A C.R.="CRLF);
		   COORD←INCHWL; NLENS←CVD(COORD);
        	   COORD←INCHWL; X←REALSCAN(COORD,MESS);
		   COORD←INCHWL; Y←REALSCAN(COORD,MESS);
		   COORD←INCHWL; Z←REALSCAN(COORD,MESS);
		   CAM_CENTER(NLENS,X,Y,Z);				END;
	BEGIN ⊃ 5; DEB_CAM←¬DEB_CAM; GOTO TES;			END;
 	END;

	OUTSTR("...TYPE Y TO  TEST AGAIN:"CRLF);
	IF INCHWL="Y" THEN BEGIN CAMFLG←0; GOTO TIT; END;
  END "TESTIT";

⊃ HERE BEGINS EXECUTION ;
	CAMFLG←0; TYP_CAM←TRUE; DEB_CAM←FALSE;
 	CAM_INIT;
        HAT;
	IF   RUN=0
 	THEN BEGIN OUTSTR("...TYPE Y FOR TEST MODE:"CRLF);
	           IF YES THEN TESTIT; END
	ELSE BEGIN
 	  PUT_DATA(0,0,"CAM");        ⊃ DECLARE YOUR NAME ;
	  OUTSTR("CAM-ACTIVATED"CRLF);
	  YES_CAM←TRUE;
 	  WHILE TRUE DO BEGIN 
	    MESS ← GET_ENTRY ('120,NULL,"CAM",NULL);
	    CAMFLG←0;
	    MESS ← QUEUE ('600,MESS); ⊃ ACTIVATE AND ACKNOWLEDGE ;
 	  END; END;
END "GILCAM";